/* * * * * * * * * * * * * * * * * * * * * *
*   Copyright (c) ycq_work@163.com
*   File:     MxgArray.h
*   Author:   ycq
*   e-mail：  ycq_work@163.com
*   Time:     2023-07-13
*   Description:
* * * * * * * * * * * * * * * * * * * * * * */

#ifndef MXGARRAY_H
#define MXGARRAY_H

#include <cstdarg>

namespace mxg::stl
{

template<typename T>
class MxgArray
{
private:
    int _size{};                                  // 当前元素数量
    int _capacity{};                              // 容量
    T *_pAddr;                                    // 元素的首地址
public:
    // 创建定长空数组
    explicit MxgArray(int capacity);

    // 根据已有数组创建新数组
    MxgArray(const MxgArray<T> &other);

    MxgArray(int count, const T &&data, ...);

    // 重载=
    MxgArray<T> &operator=(const MxgArray<T> &other);

    // MxgArray operator= (const T& data);
    // 重载[] 用于索引具体某一个元素
    T &operator[](int index);

    // at函数
    T &at(int index);

    // front函数 访问第一个元素
    T &front();

    // back 最后一个元素
    T &back();

    // push_back函数
    void push_back(T &data);

    void push_back(const T &data);

    void push_back(T &&data);

    // pop_back函数
    void pop_back();

    void clear();

    // 是否为空
    bool empty();

    // 返回数组当前元素
    int size();

    // 返回数组最大元素量
    int max_size();

    ~MxgArray();

private:
    void try_init(int capacity);
};

template<typename T>
MxgArray<T>::MxgArray(int capacity)
{
    try_init(capacity);
}

template<typename T>
MxgArray<T>::MxgArray(const MxgArray<T> &other)
{
    try_init(other._size);
    for (int i = 0; i < other._size; ++i) {
        push_back(other._pAddr[i]);
    }
}

template<typename T>
MxgArray<T>::MxgArray(const int count, const T &&data, ...)
{
    va_list args;

    va_start (args, data);

    try_init(count);

    if (this->_size < this->_capacity && this->_size == 0) {
        push_back(data);
    }

    for (int i = 1; i < count; ++i) {
        int value = va_arg (args, T);
        push_back(value);
    }

    va_end (args);

}

template<typename T>
MxgArray<T> &MxgArray<T>::operator=(const MxgArray<T> &other)
{
    if (this == &other) {
        return *this;
    }
    if (this->_pAddr != nullptr) {
        delete[] this->_pAddr;
    }

    try_init(other._size);
    for (int i = 0; i < other._size; ++i) {
        push_back(other._pAddr[i]);
    }

    return *this;
}

//template<typename T>
//MxgArray<T> MxgArray<T>::operator=(const T &data)
//{
//    if (this->pAddr != nullptr) {
//        delete[] this->pAddr;
//    }
//
//
//    return *this;
//}

template<typename T>
T &MxgArray<T>::operator[](int index)
{
    return this->_pAddr[index];
}

template<typename T>
T &MxgArray<T>::at(int index)
{
    return this->_pAddr[index];
}

template<typename T>
T &MxgArray<T>::front()
{
    return this->_pAddr[0];
}

template<typename T>
T &MxgArray<T>::back()
{
    if (this->_size == 0) {
        return this->_pAddr[this->_size];
    }
    return this->_pAddr[this->_size - 1];
}

template<typename T>
void MxgArray<T>::push_back(T &data)
{
    if (this->_size >= this->_capacity) {
        return;
    }

    this->_pAddr[this->_size] = data;

    this->_size++;
}

template<typename T>
void MxgArray<T>::push_back(const T &data)
{
    push_back(const_cast<T &>(data));
}

template<typename T>
void MxgArray<T>::push_back(T &&data)
{
    push_back(data);
}

template<typename T>
void MxgArray<T>::pop_back()
{
    if (this->_size <= 0) {
        return;
    }
    this->_pAddr[this->_size - 1] = -999999;
    this->_size--;
}

template<typename T>
void MxgArray<T>::clear()
{
    _size = 0;
}

template<typename T>
bool MxgArray<T>::empty()
{
    return _size == 0;
}

template<typename T>
int MxgArray<T>::size()
{
    return this->_size;
}

template<typename T>
int MxgArray<T>::max_size()
{
    return this->_capacity;
}

template<typename T>
MxgArray<T>::~MxgArray()
{
    if (this->_pAddr != nullptr) {
        delete[] this->_pAddr;
    }
}

// 创建数组
template<typename T>
void MxgArray<T>::try_init(int capacity)
{
    this->_capacity = capacity;
    this->_size = 0;
    // 申请内存
    this->_pAddr = new T[this->_capacity];
}

}// namespace mxg::stl



#endif // MXGARRAY_H
